package com.zyf.wjy.dao;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * 基础DAO类，提供通用的CRUD操作
 */
@Component
public abstract class BaseDao<T> {
    
    @Value("${data.storage.path}")
    private String dataPath;
    
    protected ObjectMapper objectMapper;
    protected AtomicLong idGenerator;
    
    @PostConstruct
    public void init() {
        this.objectMapper = new ObjectMapper();
        this.objectMapper.registerModule(new JavaTimeModule());
        this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        this.idGenerator = new AtomicLong(1);
        
        // 创建数据存储目录
        File dir = new File(dataPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        
        // 初始化ID生成器
        List<T> allData = findAll();
        if (!allData.isEmpty()) {
            Long maxId = allData.stream()
                .map(this::getId)
                .filter(Objects::nonNull)
                .max(Long::compareTo)
                .orElse(0L);
            idGenerator.set(maxId);
        }
    }
    
    /**
     * 获取文件名
     */
    protected abstract String getFileName();
    
    /**
     * 获取类型引用
     */
    protected abstract TypeReference<List<T>> getTypeReference();
    
    /**
     * 获取实体ID
     */
    protected abstract Long getId(T entity);
    
    /**
     * 设置实体ID
     */
    protected abstract void setId(T entity, Long id);
    
    /**
     * 获取文件路径
     */
    protected File getFile() {
        return new File(dataPath + getFileName());
    }
    
    /**
     * 读取所有数据
     */
    protected List<T> readFromFile() {
        File file = getFile();
        if (!file.exists()) {
            return new ArrayList<>();
        }
        
        try {
            return objectMapper.readValue(file, getTypeReference());
        } catch (IOException e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
    
    /**
     * 写入所有数据
     */
    protected void writeToFile(List<T> data) {
        File file = getFile();
        try {
            objectMapper.writerWithDefaultPrettyPrinter().writeValue(file, data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 查询所有
     */
    public List<T> findAll() {
        return readFromFile();
    }
    
    /**
     * 根据ID查询
     */
    public T findById(Long id) {
        return findAll().stream()
            .filter(entity -> id.equals(getId(entity)))
            .findFirst()
            .orElse(null);
    }
    
    /**
     * 保存（新增或更新）
     */
    public T save(T entity) {
        List<T> allData = findAll();
        Long id = getId(entity);
        
        if (id == null) {
            // 新增
            id = idGenerator.incrementAndGet();
            setId(entity, id);
            allData.add(entity);
        } else {
            // 更新
            final Long finalId = id;
            allData = allData.stream()
                .map(e -> finalId.equals(getId(e)) ? entity : e)
                .collect(Collectors.toList());
        }
        
        writeToFile(allData);
        return entity;
    }
    
    /**
     * 批量保存
     */
    public List<T> saveAll(List<T> entities) {
        entities.forEach(this::save);
        return entities;
    }
    
    /**
     * 删除
     */
    public boolean deleteById(Long id) {
        List<T> allData = findAll();
        boolean removed = allData.removeIf(entity -> id.equals(getId(entity)));
        if (removed) {
            writeToFile(allData);
        }
        return removed;
    }
    
    /**
     * 批量删除
     */
    public boolean deleteByIds(List<Long> ids) {
        List<T> allData = findAll();
        boolean removed = allData.removeIf(entity -> ids.contains(getId(entity)));
        if (removed) {
            writeToFile(allData);
        }
        return removed;
    }
    
    /**
     * 统计数量
     */
    public long count() {
        return findAll().size();
    }
    
    /**
     * 判断是否存在
     */
    public boolean existsById(Long id) {
        return findById(id) != null;
    }
}

